'use strict';

var utils = require('./utils');
var bind = require('./helpers/bind');
var Axios = require('./core/Axios');
var mergeConfig = require('./core/mergeConfig');
var defaults = require('./defaults');

/**
 * Create an instance of Axios
 *
 * @param {Object} defaultConfig The default config for the instance
 * @return {Axios} A new instance of Axios
 */
function createInstance(defaultConfig) {
  // 创建一个Axios的实例
  var context = new Axios(defaultConfig);
  // 1. bind 定义上下文
  // 2. instance指向Axios.prototype.request方法，且上下文指向context  所以可以直接以 instance(option) 方式调用 
  // 3. Axios.prototype.request方法有对第一个参数进行判断，如果是字符类型，当做url，所以也可以直接使用instance(url, option) 方式调用 
  var instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  // 1. 将Axios.prototype上的方法(如：get、post、put)扩展到 instance 上
  // 2. 第三个参数是指定上下文为content，这样在执行Axios原型链上的方法时，this会指向context
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  // 1. 将context对象上的自身属性和方法扩展到instance上面
  // 注：extend使用的是forEach方法对对象做for in 遍历时，只能遍历对象本身的属性，但是不会比遍历原型链上的属性
  utils.extend(instance, context);

  return instance;
}

// Create the default instance to be exported  创建要导出的默认实例
// 接收默认配置项作为参数 创建一个Axios实例，最终会作为对象导出
var axios = createInstance(defaults);

// Expose Axios class to allow class inheritance   公开Axios类  以允许类继承
axios.Axios = Axios;

// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

// Expose Cancel & CancelToken  用于创建新实例的工厂   导出取消请求的接口
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

module.exports = axios;

// Allow use of default import syntax in TypeScript  允许在TypeScript中使用默认的导入语法
module.exports.default = axios;
